package com.gph.saviorframework.wf.listener;

import com.gph.saviorframework.wf.model.ApproveInfo;
import com.gph.saviorframework.wf.model.ApproveStatus;
import com.gph.saviorframework.wf.model.ProcessResult;
import com.gph.saviorframework.wf.service.*;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.delegate.BpmnError;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component("baseListener")
public class BaseListener {

    @Autowired
    private ActivitiInsService activitiInsService;

    @Autowired
    private ActivitiHisService activitiHisService;

    @Autowired
    private ActivitiApproveInfoService activitiApproveInfoService;

    @Autowired
    private ActivitiProcessResultService activitiProcessResultService;

    @Autowired
    private ActivitiDefService activitiDefService;

    /**
     * 保存审核状态
     * @param execution
     */
    public void setProcessResult(DelegateExecution execution,String result){
        try {
            String processInsId = execution.getProcessInstanceId();

            HistoricProcessInstance processInstance = activitiInsService.findProcessInstance(processInsId);

            ProcessResult processResult = activitiProcessResultService.get(processInsId,processInstance.getBusinessKey());
            processResult.setApplyResult(result);

            activitiProcessResultService.update(processResult);
        }
        catch (Exception ex){
            throw new BpmnError("RES_ERROR");
        }
    }

    /**
     * 保存审核状态
     * @param errorCode 错误码
     * @param execution
     */
    public void setProcessResult(DelegateExecution execution,String result,String errorCode){
        try {
            String processInsId = execution.getProcessInstanceId();

            HistoricProcessInstance processInstance = activitiInsService.findProcessInstance(processInsId);

            ProcessResult processResult = activitiProcessResultService.get(processInsId,processInstance.getBusinessKey());
            processResult.setApplyResult(result);

            activitiProcessResultService.update(processResult);
        }
        catch (Exception ex){
            throw new BpmnError(errorCode);
        }
    }

    /**
     * 设置执行人
     * @param task
     * @param execution
     */
    public void setAssigneeUser(DelegateTask task, DelegateExecution execution){
        //从流程变量中获取执行人，在启动流程之前已经设置好
        Map<String,Object> variables = execution.getVariables();
        for(String key : variables.keySet()){
            //查找key==activitiid的流程变量
            if(key.equals(execution.getCurrentActivityId())){
                task.setOwner(variables.get(key).toString());//设置拥有者
                task.setAssignee(variables.get(key).toString());
            }
        }
    }

    /**
     * 判断审批是否通过
     * @param execution
     * @return
     */
    public boolean approved(DelegateExecution execution){
        List<ApproveInfo> approveInfos = new ArrayList<ApproveInfo>();
        if(execution instanceof ExecutionEntity) {
            ExecutionEntity executionEntity = (ExecutionEntity) execution;
            ActivityImpl activity = executionEntity.getActivity();
            List<PvmTransition> transitions =  activity.getIncomingTransitions();
            for(PvmTransition pvmTransition :transitions) {
                PvmActivity pvmActivity = pvmTransition.getSource();
                String pvmActivityId = pvmActivity.getId();
                HistoricActivityInstance activityInstance = activitiHisService.
                        findHistoricActivityInstanceByInsIdAndActivitiId(executionEntity.getProcessInstanceId(),pvmActivityId);
                if(activityInstance != null) {
                    List<ApproveInfo> list = activitiApproveInfoService.findByTaskId(activityInstance.getTaskId());
                    if(list != null) {
                        approveInfos.addAll(list);
                    }
                }
            }
        }

        if(approveInfos.isEmpty()) {
            throw new ActivitiException("No Approve Information found! Process Error！");
        }
        for(ApproveInfo approveInfo : approveInfos) {
            if(!approveInfo.getApproveStatus().equals(ApproveStatus.YES.name())) {
                return false;
            }
        }
        return true;
    }
}
